/*
 * memcore.c
 * Part of the !Memphis distribution
 * (c) bdb/nas, 1991-3
 */

/* compile with -dPUFFS for alternate */
/* #define DEBUG */
#include "FS.h"
/*  debug support*/
#ifdef DEBUG
#define DEBUGf printf
#else
#define DEBUGf 1?(void)0:(void)printf
#endif



#ifndef PUFFS
#define MEMFS
#endif

#ifdef MEMFS
#define FSNUM 91  /* Acorn-allocated */
#else
#define FSNUM 0xF0
#endif

#define FSERR ( (0x100+FSNUM)<<8 )

static DEFERR( mb_Lostinode,           FSERR+0xAC,  "inode lost" );
static DEFERR( mb_malloc_failed,       FSERR,       "Not enough free memory" );
static DEFERR( mb_Locked,              FSERR+0xC3,  "Locked" );
static DEFERR( mb_DirNotEmpty,         FSERR+0xB4,  "Directory Not Empty" );
static DEFERR( mb_ObjectInUse,         FSERR+8,     "Object in use" );
static DEFERR( mb_LongName,            FSERR+0xCC,  "FileName too long" );
static DEFERR( mb_NotADir,             FSERR+0xC5,  "Not a Directory" );
static DEFERR( mb_NotAFile,            FSERR+0xC5,  "Not a File" );
static DEFERR( mb_AlreadyExists,       FSERR+0xC4,  "Already exists" );
static DEFERR( mb_BadRename,           FSERR+0x9F,  "Not same disc" );
static DEFERR( mb_enddir,              FSERR,       "Read off end of directory" );
#ifdef MEMFS
char FilingSystemName[]="Mem";
char ModuleName[]="MemFS";
int FilingSystemInformationWord=0x8B800000 + FSNUM;
#else
char FilingSystemName[]="Puf";
char ModuleName[]="PUFFS";
int FilingSystemInformationWord=0x8B800000 + FSNUM;
#endif

#define FILENAMELEN 30

#ifdef DEBUG
#define DEBUGF printf
#else
#define DEBUGF 1?(void)0:(void)printf
#endif

#include "store.h"
#include "inode.h"

/*  Event stuff */
#include "ticker.h"

int tickerperiod = 100 ; /* centiseconds */

int enableticking = 1;

void ticker(void)
{ Inode_Ticker();
}

/*  Directory module */
/*
 *
 * Directory structure:
 *
 * Directory pointer is a char *
 * Each entry has a 4 byte inode, followed by a name, NUL-terminated.
 */
#define DINODE( x ) ( *( int * )x->pos )
#define DNAME( x ) ( (x->pos)+4 )
#define DLEN( x ) (~3&8+x)
#define DMORE( x ) (x->pos)

#define DIRPAGESIZE 512         /* directories come in pages of this size */
#define DIRPAGEMARK -3          /* DINODE set to this for no more on this page */

typedef struct DIR
{ char buf[DIRPAGESIZE];
  char *pos;            /* pointer into dirbuf for current elt */
  int off;              /* offset of current page in directory */
  int len;              /* total length of directory */
  INODE *inode;
} DIR;

static DIR *dir_open(INODE *h)
{ DIR *p;
  p = malloc(sizeof(DIR));
  if (!p)
    return NULL;
  DEBUGf("dir_open(%d)=%p\n",h->inode,p);
  p->inode = Inode_Dup(h);
  p->len = h->d.length;
  p->off = 0;
  if (p->len && !Inode_Read( p->inode, p->off, (p->len-p->off)>DIRPAGESIZE?DIRPAGESIZE:(p->len-p->off), p->buf ))
    p->pos = p->buf;
  else
    p->pos = NULL;
  return p;
}

static _kernel_oserror *dir_close(DIR *p)
{
  DEBUGf("dir_close(%p)\n",p);
  if (p)
  { Inode_Lose(p->inode);
    free(p);
  }
  return NULL;
}

static _kernel_oserror *dir_next( DIR *p )
{ _kernel_oserror *err;
  DEBUGf("dir_next(%p)\n",p);
  if (!p->pos)
    return ERR(mb_enddir);
  p->pos+=DLEN(strlen(DNAME(p)));
  if (p->pos-p->buf>=p->len-p->off)
    p->pos = NULL;
  else if (DINODE(p)==DIRPAGEMARK)
  { p->off+=DIRPAGESIZE;
    err = Inode_Read( p->inode, p->off, (p->len-p->off)>DIRPAGESIZE?DIRPAGESIZE:(p->len-p->off), p->buf );
    if (err)
    { p->pos = NULL;
      return err;
    }
    else
      p->pos = p->buf;
  }
  return NULL;
}

static _kernel_oserror *dir_add( DIR *p, int inode, char *name )
{ int off,len;
  _kernel_oserror *err;
  DEBUGf("dir_add(%p,%d,%s)\n",p,inode,name);
  off = p->len % DIRPAGESIZE;
  if (p->len-off!=p->off)
  { p->off = p->len-off;
    err = Inode_Read( p->inode, p->off, (p->len-p->off)>DIRPAGESIZE?DIRPAGESIZE:(p->len-p->off), p->buf );
    if (err)
      return err;
  }
  p->pos = &p->buf[off];
  len = DLEN(strlen(name));
  if (off+len>DIRPAGESIZE-4)
  { DINODE(p) = DIRPAGEMARK;
    p->len += DIRPAGESIZE - off + len;
    err = Inode_EnsureSize(p->inode,p->len);
    if (!err)
      err = Inode_Write( p->inode, p->off, (p->len-p->off)>DIRPAGESIZE?DIRPAGESIZE:(p->len-p->off), p->buf );
    if (err)
      return err;
    p->off += DIRPAGESIZE;
    p->pos = p->buf;
  }
  else
  { p->len += len;
    err = Inode_EnsureSize(p->inode,p->len);
    if (err)
      return err;
  }
  DINODE(p)=inode;
  strcpy(DNAME(p),name);
  p->inode->d.length=p->len;
  Inode_Changed(p->inode);
  err = Inode_Write( p->inode, p->off, (p->len-p->off)>DIRPAGESIZE?DIRPAGESIZE:(p->len-p->off), p->buf );
  return err;
}

static _kernel_oserror *dir_del( DIR *p )
{ int n;
  _kernel_oserror *err;
  if (!p->pos)
    return ERR(mb_enddir);
  n=DLEN(strlen(DNAME(p)));
  DEBUGf("dir_del(%p)\n",p);
  memcpy(p->pos,p->pos+n,&p->buf[DIRPAGESIZE]-p->pos-n);
  if (p->len-p->off<=DIRPAGESIZE)
  { p->len-=n;
    p->inode->d.length=p->len;
    Inode_Changed(p->inode);
  }
  err = Inode_Write( p->inode, p->off, (p->len-p->off)>DIRPAGESIZE?DIRPAGESIZE:(p->len-p->off), p->buf );
  if (err)
    return err;
  if (p->pos==p->buf && DINODE(p)==DIRPAGEMARK) /* dead page */
  { if (p->off+DIRPAGESIZE<p->len) /* not last page */
    { while (p->off+DIRPAGESIZE<p->len)
      { err = Inode_Read( p->inode, p->off+DIRPAGESIZE, (p->len-p->off-DIRPAGESIZE)>DIRPAGESIZE?DIRPAGESIZE:(p->len-p->off-DIRPAGESIZE), p->buf );
        if (!err)
          err =Inode_Write( p->inode, p->off, (p->len-p->off)>DIRPAGESIZE?DIRPAGESIZE:(p->len-p->off), p->buf );
        if (err) return err;
        p->off += DIRPAGESIZE;
      }
      p->len -= DIRPAGESIZE;
    }
    else
    { p->len = p->off;
      if (p->off)
      { p->off-=DIRPAGESIZE;
        err = Inode_Read( p->inode, p->off, (p->len-p->off)>DIRPAGESIZE?DIRPAGESIZE:(p->len-p->off), p->buf );
        if (err) return err;
        p->pos = p->buf;
        while (DINODE(p)!=DIRPAGEMARK)
          p->pos+=DLEN(strlen(DNAME(p)));
        p->len-=DIRPAGESIZE-(p->pos-p->buf);
      }
    }
    err = Inode_EnsureSize(p->inode,p->len);
    if (err) return err;
    p->inode->d.length = p->len;
    Inode_Changed(p->inode);
  }
  return NULL;
}

/*  FileEntry module */

struct FileEntry
{       INODE   *inode;
        char    name[FILENAMELEN+1];
};

static FileEntry *inodeFileEntry( INODE *d, char *name )
{
  FileEntry *fe;
  fe=malloc( sizeof( FileEntry ) );
  DEBUGf("Wrapped %p(%s) as %p context %p mode ??\n",d,name,fe,&fe /*, _kernel_processor_mode() */);
  if ( !fe )
    return NULL;
  fe->inode = d;
  strcpy( fe->name, name );
  return fe;
}

void *private_word;

_kernel_oserror * Initialise_FileEntrys( void *privw )
{
  _kernel_oserror *err=Inode_Init();
  private_word = privw;
  if (!err)
  { enableticking=1;
    setcallafter(privw);
  }
  return err;
}

static INODE *find_root(char *volname)
{
  storeid s = Store_Find(special_field,volname);
  INODE *inode = Inode_Find(s,1);
  return inode;
}

_kernel_oserror *FileEntry_FreeSpace( FileEntry *fe, struct freespace *b )
{
  return Store_FreeSpace(fe->inode->store,b);
}

void Terminate_FileEntrys( void )
{
  ShutDown_FileEntrys();
}

void ShutDown_FileEntrys( void )
{
  killticking(private_word);
  Inode_Finish();
}

_kernel_oserror *DoCommand( int cmd_no, int argc, char *argv[] )
{
  _kernel_swi_regs r;
  argc = argc;
  /*
          Switch between the commands
  */
  switch ( cmd_no )
  {
  case 0: /*      *FSname       */

          r.r[0] = FSControl_SelectFilingSystem;
          r.r[1] = ( int )FilingSystemName;
          return _kernel_swi( XOS_Bit | OS_FSControl, &r, &r );
  case 1:
          return reportusage( argc>0?argv[1]:"" );
  default:
          return ERR( mb_BadParameters );
  }
}

/*
        This is the SWI handler
*/
_kernel_oserror *fs_swi
( 
        int swi_number, 
        _kernel_swi_regs *r, 
        void *private_word
 )
{
        _kernel_oserror *err = NULL;

        r = r;
        private_word = private_word;

        switch ( swi_number )
        {
        default:
                err = NULL;
                break;
        }

        return err;
}

static char *popnode( char *name, char *buf )
{
  char *p;
  int n;
  p=strchr( name, '.' );
  n=p?p-name:strlen( name );
  if ( n>FILENAMELEN )
    return ( char * )-1;
  strncpy( buf, name, n );
  buf[n]=0;
  if ( p )
    ++p;
  return p;
}

_kernel_oserror *FileEntry_DirScan( FileEntry *dir, int i, FileDesc *d, char **name )
{ INODE *h;
  DIR *x;
  _kernel_oserror *err;
  static char namebuf[FILENAMELEN];
  DEBUGf("FileEntry_DirScan(%s[%d],%d)\n",dir->name,dir->inode->uses,i);
  if ( dir->inode->d.type!=2 )
    return ERR( mb_NotADir );
  for ( x = dir_open(dir->inode); x && DMORE(x); )
  { if ( !i-- )
    { h = Inode_Find( dir->inode->store, DINODE( x ) );
      if (!h)
      { dir_close(x); return ERR(mb_Lostinode); }
      *d = h->d;
      Inode_Lose(h);
      *name = namebuf;
      strcpy(namebuf,DNAME( x ));
      return dir_close(x);
    }
    err = dir_next(x);
    if (err) return err;
  }
  dir_close(x);
  return ERR(mb_FileNotFound);
}

_kernel_oserror *FileEntry_Find( FileEntry *fe, char *name, FileDesc *d )
{ _kernel_oserror *err;
  FileEntry *ofe;
  DEBUGf("FileEntry_Find(%s[%d],%s)\n",FileEntry_Name(fe),fe?fe->inode->uses:42,name);
  normalise( &fe, &name );
  err = FileEntry_Open( fe, name, OPENIN, &ofe );
  if ( err )
    return err;
  *d = FileEntry_Desc( ofe );
  return FileEntry_Close( ofe );
}

static _kernel_oserror *finddirentry( INODE*dir, char *name, WHICH which, INODE **rh, DIR **where );

_kernel_oserror *FileEntry_Open(FileEntry *dfe, char *name, WHICH which, FileEntry **rfe )
{
  INODE *rh,*dir;
  char *dname;
  DIR *w;
  _kernel_oserror *err;
  DEBUGf("FileEntry_Open(%s[%d],%s,%d)\n",FileEntry_Name(dfe),dfe?dfe->inode->uses:42,name,which);
  normalise( &dfe, &name );
  if (!dfe)
  { dir=find_root(NULL);
    if (!dir)
      return ERR( mb_FileNotFound );
    dname="$";
  }
  else
  { dir=Inode_Dup(dfe->inode);
    dname=dfe->name;
  }
  if ( !name || !name[0] )
  { *rfe=inodeFileEntry(dir,dname);
    if (!*rfe)
    { Inode_Lose(dir); return ERR(mb_malloc_failed); }
    return NULL;
  }
  err = finddirentry( dir, name, OPENIN, &rh, &w );
  if ( which<OPENIN )
  { if ( err )
    { rh = Inode_New(dir);
      if (!rh)
      { Inode_Lose(dir); return ERR(mb_malloc_failed); }
      if (which==CREATEDIR)
      { rh->d.type = 2;
        StampInfo(&rh->d.info);
        Inode_Changed(rh);
      }
      err = finddirentry( dir, name, which, &rh, &w );
      if (err)
        Inode_Delete(rh);
    }
  }
  Inode_Lose(dir);
  if ( err )
  { *rfe = NULL;
    return err;
  }
  if ( which==CREATE )
  { if ( rh->d.type==2 )
    {
      *rfe=NULL;
      Inode_Lose(rh);
      dir_close(w);
      return ERR(mb_NotAFile);
    }
    else
    { rh->d.length = 0;
      Inode_Changed(rh);
    }
  }
  else if ( which==CREATEDIR )
  { if ( rh->d.type == 2 )
    {
    }
    else
    { *rfe=NULL;
      Inode_Lose(rh);
      dir_close(w);
      return ERR(mb_NotADir);
    }
  }
  *rfe = inodeFileEntry( rh, w?DNAME( w ):"$" );
  dir_close(w);
  if (!*rfe)
  { Inode_Lose(rh); return ERR(mb_malloc_failed); }
  return NULL;
}

/* if (create), add entry else find one
 * return position where found in where, or NULL for root
 */

static _kernel_oserror *finddirentry( INODE *dir, char *name, WHICH which, INODE **rh, DIR **where ) 
{
  char buf[100];
  INODE *h,*inode;
  DIR *x;
  _kernel_oserror *err;
  DEBUGf("finddirentry(%p[%d],%s,%d)\n",dir,dir?dir->uses:42,name,which);
  if ( !dir )
  { dir=find_root(NULL);
    if (!dir)
      return ERR( mb_FileNotFound );
  }
  else
    dir = Inode_Dup(dir);
  switch( name[0] )
  {
  case '$':
    Inode_Lose(dir);
    if (name[1] && name[1]!='.')
      return ERR( mb_FileNotFound );
    dir=find_root(NULL);
    if (!dir)
      return ERR( mb_FileNotFound );
    if ( !name[1] )
    {
returnroot:
        inode=Inode_Dup(dir);
        x=NULL;
        goto returninode;
    }
    name+=2;
    break;
  case ':':
    name=popnode( name+1, buf );
    Inode_Lose(dir);
    dir=find_root(buf);
    if (!dir)
      return ERR( mb_FileNotFound );
    if ( !name )
      goto returnroot;
    if ( name[0]=='$' )
    { if (!name[1])
        goto returnroot;
      else if (name[1]!='.')
      { Inode_Lose(dir); return ERR( mb_FileNotFound ); }
      name+=2;
    }
    break;
  }
searchinode:
  if ( dir->d.type!=2 )
  { Inode_Lose(dir); return ERR( mb_NotADir ); }
  name = popnode( name, buf );
  if ( name==( char * )-1 )
    { Inode_Lose(dir); return ERR( mb_LongName ); }
  if ( buf[0]=='^' && !buf[1] )
  {
    if (dir->inode==1)
    { inode = Inode_Dup(dir);
      x = NULL;
      goto foundobj;
    }
    inode = Inode_Find( dir->store,dir->parentinode );
    if ( !inode )
      { Inode_Lose(dir); return ERR( mb_Lostinode ); }
    h = Inode_Find( inode->store,inode->parentinode );
    if ( !h )
    { Inode_Lose(inode); Inode_Lose(dir); return ERR( mb_Lostinode ); }
    for ( x = dir_open( h ); x && DMORE(x); )
    { if ( DINODE( x )==inode->inode )
      { Inode_Lose(h);
        goto foundobj;
      }
      err = dir_next(x);
      if (err) return err;
    }
    dir_close(x);
    Inode_Lose(inode);
    Inode_Lose(h);
    Inode_Lose(dir); 
    return ERR( mb_FileNotFound );
  }
  for ( x = dir_open( dir ); x && DMORE(x); )
  { if ( !stricmp( DNAME( x ), buf ) )
      { inode = Inode_Find( dir->store,DINODE(x) );
        if (!inode)
        { dir_close(x); Inode_Lose(dir); return ERR( mb_Lostinode ); }
foundobj:
        if ( name )
        { Inode_Lose(dir);
          dir=inode;
          dir_close(x); 
          goto searchinode;
        }
        if ( which<OPENIN )
        { dir_close(x); Inode_Lose(dir); Inode_Lose(inode); return ERR(mb_AlreadyExists); }
        goto returninode;
      }
    err = dir_next(x);
    if (err) return err;
  }
  if ( which>=OPENIN || name )
  { dir_close(x); Inode_Lose(dir); return ERR( mb_FileNotFound ); }
  inode = *rh;
  err = dir_add( x, inode->inode, buf );
  if (err) return err;
  inode->parentinode = dir->inode;
  Inode_Changed(inode);
returninode:
  Inode_Lose(dir);
  *rh=inode;
  *where=x;
  return NULL;
}

_kernel_oserror *FileEntry_Close( FileEntry *fe )
{
  DEBUGf("FileEntry_Close(%s)[%d]\n",FileEntry_Name(fe),fe?fe->inode->uses:42);
  if ( fe )
  { Inode_Lose(fe->inode);
    free( fe );
  }
  return NULL;
}

_kernel_oserror *FileEntry_Delete( FileEntry *dir, char *name, FileDesc *d )
{
  INODE *h,*dh;
  DIR *w;
  _kernel_oserror *err;
#ifdef DEBUG
  printf( " Delete dir=%s[%d] name=%s\n", FileEntry_Name(dir),dir?dir->inode->uses:42, name?name:"NULL" );
#endif
  normalise( &dir, &name );
  if ( !name )
    return ERR( mb_ObjectInUse );
  if (!dir)
  { dh=find_root(NULL);
    if (!dh)
      return ERR( mb_FileNotFound );
  }
  else
    dh=Inode_Dup(dir->inode);
  err = finddirentry( dh, name, OPENIN, &h, &w );
  Inode_Lose(dh);
  if ( err )
    return err;
#ifdef DEBUG
  printf( " Delete h=%p\n", h );
#endif
  if ( h->d.attr&Attr_L )
  { Inode_Lose(h); dir_close(w); return ERR( mb_Locked ); }
  if ( h->d.type==2 && h->d.length>0 || !w )
  { Inode_Lose(h); dir_close(w); return ERR( mb_DirNotEmpty ); }
  *d = h->d;
  Inode_Delete(h);
  dir_del(w);
  dir_close(w); 
  return NULL;
}

_kernel_oserror *FileEntry_Rename( FileEntry *dir, char *name, FileEntry *newdir, char *newname )
{
  INODE *h;
  DIR *w1,*w2;
  _kernel_oserror *err;
  DEBUGf("FileEntry_Rename(%s[%d],%s,%s[%d],%s)\n",dir->name,dir?dir->inode->uses:42,name,newdir->name,newdir?newdir->inode->uses:42,newname);
  normalise( &dir, &name );
  normalise( &newdir, &newname );
  err = finddirentry( dir?dir->inode:NULL, name, OPENIN, &h, &w1 );
  if ( err )
    return err;
  if ( h->d.attr&Attr_L || !w1 )
  { Inode_Lose(h); dir_close(w1); return ERR( mb_Locked ); }
  err = finddirentry( newdir?newdir->inode:NULL, newname, CREATE, &h, &w2 );
  if ( err )
  { Inode_Lose(h); dir_close(w1); return err; }
  if ( !w2 || w1->inode->store != w2->inode->store )
  { Inode_Lose(h); dir_close(w1); return ERR(mb_BadRename); }
  if (w1->inode==w2->inode)
  { dir_close(w1);
    dir_close(w2);
    Inode_Lose(h);
    err = finddirentry( dir?dir->inode:NULL, name, OPENIN, &h, &w1 );
    if ( err )
      return err;
  }
  else
    dir_close(w2);
  Inode_Lose(h);
  dir_del(w1);
  dir_close(w1);
  return NULL;
}

_kernel_oserror *FileEntry_GetBytes( FileEntry *fe, char *p, int o, int n, int *newpos, int *len )
{
  DEBUGf("FileEntry_GetBytes(%s[%d],%p,%d,%d)\n",FileEntry_Name(fe),fe?fe->inode->uses:42,p,o,n);
  *newpos = o+n; *len = n;
  return Inode_Read( fe->inode, o, n, p );
}

_kernel_oserror * FileEntry_GetByte( FileEntry *fe, int *b )
{
  fe = fe;
  b = b;
  return ERR(mb_BadParameters);
}

_kernel_oserror *FileEntry_PutBytes( FileEntry *fe, char *p, int o, int n, int *newpos )
{ _kernel_oserror *err;
  DEBUGf("FileEntry_PutBytes(%s[%d],%p,%d,%d)\n",FileEntry_Name(fe),fe?fe->inode->uses:42,p,o,n);
  *newpos = n+o;
  if ( n+o>fe->inode->d.length )
  { if ( ( err = FileEntry_SetLength( fe, n+o ) )!=NULL )
      return err;
  }
  if ( n )
  { err = Inode_Write( fe->inode, o, n, p );
    o+=n;
    return err;
  }
  return NULL;
}

_kernel_oserror *FileEntry_PutByte( FileEntry *fe , int c )
{
  fe = fe;
  c = c;
  return ERR(mb_BadParameters);
}

static char zero[512];

_kernel_oserror *FileEntry_PutZeros( FileEntry *fe, int o, int n )
{ _kernel_oserror *err=NULL;
  DEBUGf("FileEntry_PutZeros(%s[%d],%d,%d)\n",FileEntry_Name(fe),fe?fe->inode->uses:42,o,n);
  if ( n+o>fe->inode->d.length )
  { if ( ( err = FileEntry_SetLength( fe, n+o ) )!=NULL )
      return err;
  }
  while ( n>512 )
  { err=Inode_Write( fe->inode, o, 512, zero );
    o+=512; n-=512;
  }
  if (n)
  { err=Inode_Write( fe->inode, o, n, zero );
    o+=n;
  }
  return NULL;
}

_kernel_oserror *FileEntry_EnsureSize( FileEntry *fe, int size )
{
  DEBUGf("FileEntry_EnsureSize(%s[%d],%d)\n",FileEntry_Name(fe),fe?fe->inode->uses:42,size);
  if ( size <= fe->inode->allocated )
    return NULL;
  return Inode_EnsureSize( fe->inode, size );
}

_kernel_oserror *FileEntry_SetLength( FileEntry *fe, int length )
{ _kernel_oserror *err;
  DEBUGf("FileEntry_SetLength(%s[%d],%d)\n",FileEntry_Name(fe),fe?fe->inode->uses:42,length);
  if ( NULL!=( err=FileEntry_EnsureSize( fe, length ) ) )
    return err;
  fe->inode->d.length = length;
  Inode_Changed( fe->inode );
  return NULL;
}

_kernel_oserror *FileEntry_Access( FileEntry *dir, char *name, int attr )
{ FileEntry *fe;
  _kernel_oserror *err;
  DEBUGF("Access %s[%d] %s %x\n",FileEntry_Name(dir),dir?dir->inode->uses:42,name?name:"NULL",attr);
  err = FileEntry_Open(dir,name,OPENIN,&fe);
  if (err)
    return err;
  fe->inode->d.attr = attr;
  Inode_Changed( fe->inode );
  FileEntry_Close(fe);
  return NULL;
}

_kernel_oserror *FileEntry_SetInfo( FileEntry *fe, Information_Fields info )
{
  DEBUGf("FileEntry_SetInfo(%s)[%d]\n",FileEntry_Name(fe),fe->inode->uses);
  fe->inode->d.info = info;
  Inode_Changed( fe->inode );
  return NULL;
}

_kernel_oserror *FileEntry_Flush ( FileEntry *fe )
{
  DEBUGf("FileEntry_Flush(%s)[%d]\n",FileEntry_Name(fe),fe?fe->inode->uses:42);
  return NULL;
}

_kernel_oserror *FileEntry_SetSeqPtr( FileEntry *fe , int seqptr )
{
  DEBUGf("FileEntry_SetSeqPtr(%s)[%d] %d\n",FileEntry_Name(fe),fe?fe->inode->uses:42,seqptr);
  return ERR(mb_BadParameters);
}

void FileEntry_FileInfoObject
( 
  FileEntry *fse
 )
{
  DEBUGf("FileEntry_FileInfoObject(%s)[%d]\n",FileEntry_Name(fse),fse?fse->inode->uses:42);
  printf( "%-20s %8p %8p %8x %8x %7p %7p %7x %d\n\r", 
           fse->name, 
           fse->inode->d.info.load_exec.load_address, 
           fse->inode->d.info.load_exec.execute_address, 
           fse->inode->d.length, 
           fse->inode->d.attr, 
           fse, 
           fse->inode, 
           fse->inode->allocated, 
           fse->inode->uses );
}

char *FileEntry_DiscName( FileEntry *fe )
{
  DEBUGf("FileEntry_DiscName(%s)[%d]\n",FileEntry_Name(fe),fe?fe->inode->uses:42);
  if (!fe)
    return "\"Unset\"";
  return Store_Name(fe->inode->store);
}

char *FileEntry_SpecialField( FileEntry *fe )
{
  DEBUGf("FileEntry_SpecialField(%s)[%d]\n",FileEntry_Name(fe),fe?fe->inode->uses:42);
  if (!fe)
    return NULL;
  return Store_SpecialField(fe->inode->store);
}

char *FileEntry_Name( FileEntry *fe )
{
  return fe?fe->name:"\"Unset\"";
}

FileDesc FileEntry_Desc( FileEntry *fe )
{
  DEBUGf("FileEntry_Desc(%s)[%d]\n",FileEntry_Name(fe),fe?fe->inode->uses:42);
  return fe->inode->d;
}

int FileEntry_SeqPtr( FileEntry *fe )
{
  DEBUGf("FileEntry_SeqPtr(%s)[%d]\n",FileEntry_Name(fe),fe?fe->inode->uses:42);
  return -1;
}

int FileEntry_Allocated( FileEntry *fe )
{ return fe->inode->allocated;
}
